package org.liveboardgames.agricola.control.delegates.harvest
{
	import com.adobe.cairngorm.control.CairngormEventDispatcher;

	import flash.utils.setTimeout;

	import mx.collections.ListCollectionView;
	import mx.events.CollectionEvent;

	import org.liveboardgames.agricola.control.delegates.helper.GameHelper;
	import org.liveboardgames.agricola.control.events.HarvestFieldEvent;
	import org.liveboardgames.agricola.control.events.HarvestStepCompleteEvent;
	import org.liveboardgames.agricola.model.AgricolaModelLocator;
	import org.liveboardgames.agricola.model.PopupModel;
	import org.liveboardgames.agricola.model.enums.HarvestStepEnum;
	import org.liveboardgames.agricola.vo.Game;
	import org.liveboardgames.agricola.vo.player.Player;
	import org.liveboardgames.common.dictionary.collections.HashCollection;

	public class HarvestController
	{
		private var game:Game;

		/** Introduced as a "lock", to avoid races between the update of the 
		 * harvestBreedPlayers and the resetHarvest. */
		public var isFinished:Boolean;

		public function HarvestController(game:Game)
		{
			this.game = game;
			if (this.game.harvestBreedPlayers == null)
			{
				this.game.harvestBreedPlayers = new HashCollection();
			}
			if (this.game.harvestFeedPlayers == null)
			{
				this.game.harvestFeedPlayers = new HashCollection();
			}
			if (this.game.harvestFieldPlayers == null)
			{
				this.game.harvestFieldPlayers = new HashCollection();
			}
			this.game.harvestBreedPlayers.addEventListener(CollectionEvent.COLLECTION_CHANGE, onHarvestStepComplete);
			this.game.harvestFeedPlayers.addEventListener(CollectionEvent.COLLECTION_CHANGE, onHarvestStepComplete);
			this.game.harvestFieldPlayers.addEventListener(CollectionEvent.COLLECTION_CHANGE, onHarvestStepComplete);
			this.isFinished = false;
		}

		public function startHarvest():void
		{
			var harvestStep:String = getHarvestStep(game);

			if (harvestStep != null && !isFinished)
			{
				var currentHarvestingPlayer:Player = game.currentPlayer;

				if (HarvestStepEnum.FIELD == harvestStep)
				{
					// There is no player input needed at this step (for now, 
					// as this will change with the cards)
					var harvestFieldEvent:HarvestFieldEvent = new HarvestFieldEvent(HarvestFieldEvent.HARVEST_FIELD);
					harvestFieldEvent.player = currentHarvestingPlayer;
					CairngormEventDispatcher.getInstance().dispatchEvent(harvestFieldEvent);
				}
				else if (HarvestStepEnum.FEED == harvestStep)
				{
					// Here use popups, which will dispatch an event and 
					// update the game harvestFeedPlayer list, which will in
					// turn trigger the next phase of harvest 
					var cookingPlaces:ListCollectionView = GameHelper.getCookingPlaces(currentHarvestingPlayer.farm);
					var foodNeded:int = GameHelper.computeFoodForHarvest(currentHarvestingPlayer);

					AgricolaModelLocator.getInstance().popups.currentActionPopupIndex = PopupModel.POPUP_HARVEST_FEED;
					AgricolaModelLocator.getInstance().popups.cookingPlaces = cookingPlaces;
					AgricolaModelLocator.getInstance().popups.foodNeeded = foodNeded;
				}
				else if (HarvestStepEnum.BREED == harvestStep)
				{
					if (GameHelper.getNewBornAnimals(currentHarvestingPlayer.farm) != null)
					{
						AgricolaModelLocator.getInstance().popups.currentActionPopupIndex = PopupModel.POPUP_HARVEST_BREED;
					}
					else
					{
						var harvestStepCompleteEvent:HarvestStepCompleteEvent = new HarvestStepCompleteEvent(HarvestStepCompleteEvent.
							HARVEST_STEP_COMPLETE);
						harvestStepCompleteEvent.step = HarvestStepEnum.BREED;
						harvestStepCompleteEvent.player = currentHarvestingPlayer;
						CairngormEventDispatcher.getInstance().dispatchEvent(harvestStepCompleteEvent);
					}
				}
				else
				{
					throw new Error("Invalid harvest step: " + harvestStep);
				}
			}

		}

		private function onHarvestStepComplete(event:CollectionEvent):void
		{
			AgricolaModelLocator.getInstance().popups.currentActionPopupIndex = PopupModel.POPUP_NO_ACTION_INDEX;

			// Make sure that we wait till the current player is updated
			setTimeout(startHarvest, 100);
		}

		private function getHarvestStep(game:Game):String
		{
			var currentStep:String = null;

			if (game.harvestFieldPlayers.length != game.players.length)
			{
				currentStep = HarvestStepEnum.FIELD;
			}
			else if (game.harvestFeedPlayers.length != game.players.length)
			{
				currentStep = HarvestStepEnum.FEED;
			}
			else if (game.harvestBreedPlayers.length != game.players.length)
			{
				currentStep = HarvestStepEnum.BREED;
			}

			return currentStep;
		}

		private function getHarvestingPlayer(game:Game, harvestStep:String):Player
		{
			var harvestingPlayer:Player = null;

			// Iterate in the order of the turn
			for each (var player:Player in game.players)
			{
				var playerList:ListCollectionView = getPlayerListFromHarvestStep(game, harvestStep);
				if (!playerList.contains(player))
				{
					harvestingPlayer = player;
					break;
				}
			}

			return harvestingPlayer;
		}

		private function getPlayerListFromHarvestStep(game:Game, harvestStep:String):ListCollectionView
		{
			var result:ListCollectionView = null;

			if (HarvestStepEnum.FIELD == harvestStep)
			{
				result = game.harvestFieldPlayers;
			}
			else if (HarvestStepEnum.FEED == harvestStep)
			{
				result = game.harvestFeedPlayers;
			}
			else if (HarvestStepEnum.BREED == harvestStep)
			{
				result = game.harvestBreedPlayers;
			}

			return result;
		}
	}
}